package preprocessor;

import java.util.HashSet;
import entities.concept.AndConcept;
import entities.concept.Concept;
import entities.concept.DomainConceptEQ;
import entities.concept.DomainConceptLT;
import entities.concept.DomainConceptLTEQ;
import entities.concept.ExistsConcept;
import entities.concept.NotConcept;
import entities.concept.OrConcept;
import entities.concept.PConcept;
import entities.concept.UniversalConcept;
/**
 * This class simplifies axioms/concepts
 * @author j55wu
 *
 */
public class Simplification {
	
	
	public static HashSet<Concept> NNF(HashSet<Concept> cs){
		HashSet<Concept> ret = new HashSet<Concept>();
		for(Concept c:cs){
			ret.add(NNF(c, false));
		}
		return ret;
	}
	
	//push the negation inside
	public static Concept NNF(Concept c, boolean hasnot){
		if(c == null){
			return null;
		}
		Concept fin=null;
		boolean found = hasnot;		
		try{						
			if(c instanceof AndConcept){
				AndConcept and = (AndConcept) c;
				HashSet<Concept> res = new HashSet<Concept>();	
				for(Concept ac:and.getConceptSet()){
					res.add(NNF(ac, found));
				}
				if(found) fin = new OrConcept(res);
				else fin = new AndConcept(res);
				}
			else if(c instanceof UniversalConcept){
				UniversalConcept allres =(UniversalConcept) c;	
				if(!found) {
					fin = new UniversalConcept(allres.getRole(),NNF(allres.getFiller(), found));
				}
				else{
					fin = new ExistsConcept(allres.getRole(),NNF(allres.getFiller(), found));
				}
			}
			else if(c instanceof PConcept){				
				PConcept myclass =(PConcept)c;				
				if(!found) fin = myclass;
				else fin = new NotConcept(myclass);
			}			
			else if(c instanceof OrConcept){						
				OrConcept or = (OrConcept) c;
				HashSet<Concept> res = new HashSet<Concept>();	
				for(Concept oc : or.getConceptSet()){
					res.add(NNF(oc, found));
				}
				if (found ) fin = new AndConcept(res);
				else fin=new OrConcept(res);
			}			
			else if(c instanceof ExistsConcept){
				ExistsConcept someres =(ExistsConcept) c;
				if(!found) {
					fin = new ExistsConcept(someres.getRole(), NNF(someres.getFiller(), found));
				}
				else{
					fin = new UniversalConcept(someres.getRole(), NNF(someres.getFiller(), found));
				}
			}
			else if(c instanceof NotConcept){
				NotConcept not = (NotConcept) c;	
				fin = NNF(not.getConcept(),!found);
				}	
			else if(c instanceof DomainConceptEQ){
				DomainConceptEQ<?,?> dce = (DomainConceptEQ<?,?>)c;
				if(!found){
					fin = c;
				}else{
					//f = g  is the same as f>g or f<g
					HashSet<Concept> os = new HashSet<Concept>();
					os.add(new DomainConceptLT<Object, Object>(dce.getFeature(), dce.getValue()));
					os.add(new DomainConceptLT<Object, Object>(dce.getValue(), dce.getFeature()));
					fin = new OrConcept(os);
				}
			}
			else if(c instanceof DomainConceptLT){
				DomainConceptLT<?,?> dce = (DomainConceptLT<?,?>)c;
				if(!found){
					fin = c;
				}else{
					//! f < g  is the same as f>=g, 
					//HashSet<Concept> os = new HashSet<Concept>();
					//os.add(new DomainConceptEQ<?,?>(dce.getFeature(), dce.getValue()));
					//os.add(new DomainConceptLTEQ(dce.getValue(), dce.getFeature()));
					fin = new DomainConceptLTEQ<Object, Object>(dce.getValue(), dce.getFeature());
				}
			}
			else if(c instanceof DomainConceptLTEQ){
				DomainConceptLTEQ<?,?> dce = (DomainConceptLTEQ<?,?>)c;
				if(!found){
					fin = c;
				}else{
					//! f<=g  is the same as f>g
					//HashSet<Concept> os = new HashSet<Concept>();
					//os.add(new DomainConceptLT(dce.getValue(), dce.getFeature()));
					fin = new DomainConceptLT<Object, Object>(dce.getValue(), dce.getFeature());
				}
			}
			//further extensions go here...
			else{
				System.out.println("Items not handle by current NNF algorithm: "+c);
			}
			}catch(Exception err){
				err.printStackTrace();
			}	
			return  fin;
	}
	
	

}
